package com.sky.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.OrderPayStatusConstant;
import com.sky.constant.OrderStatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.Address;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    private final Long INIT_HOUR = 1l;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserShopingCartMapper shopingCartMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private Order_detailMapper orderDetailMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Transactional
    public OrderSubmitVO submitorder(OrdersSubmitDTO dto){
        log.info("用户下单dto：{}",dto);
        //判断业务异常逻辑（购物车为空或者没有选择地址）
        Long userid = BaseContext.getCurrentId();
        ShoppingCart cart = new ShoppingCart();
        cart.setUserId(userid);
        List<ShoppingCart> list = shopingCartMapper.getBydishId_or_setmealId_or_userid(cart);
        AddressBook addressBook = addressBookMapper.getByid(dto.getAddressBookId().intValue());
        if(list == null){
            //购物车为空
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }else if(addressBook == null){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }//地址为空

        //查出地址
        AddressBook addressBook_ = addressBookMapper.getByid(dto.getAddressBookId().intValue());
        String address = addressBook_.getProvinceName()+addressBook_.getCityName()+addressBook_.getDistrictName()+addressBook_.getDetail();
        //往order表插入一条订单
        Orders order = new Orders();
        BeanUtils.copyProperties(dto,order);
        order.setOrderTime(LocalDateTime.now());
        order.setNumber(String.valueOf(System.currentTimeMillis()));//时间戳为当前订单号
        order.setPayStatus(OrderPayStatusConstant.UN_PAIDED);
        order.setStatus(OrderStatusConstant.PendingOrders);
        order.setEstimatedDeliveryTime(order.getOrderTime().plusHours(INIT_HOUR));
        order.setRemark(dto.getRemark());
        order.setAddress(address);
        BeanUtils.copyProperties(addressBook,order);
        log.info("用户下单返回的order：{}",order);
        orderMapper.insert(order);//插入订单
        //往order_detail插入多条明细（要插入的商品来自购物车）
        List<OrderDetail> orderDetailList = new ArrayList<>();
        for(int k=0;k<list.size();k++){
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(order.getId());
            BeanUtils.copyProperties(list.get(k),orderDetail);
            orderDetailList.add(orderDetail);
        }
        orderDetailMapper.insert(orderDetailList);
        //封装返回结果

        OrderSubmitVO vo = new OrderSubmitVO();
        vo.setId(order.getId());
        vo.setOrderTime(order.getOrderTime());
        vo.setOrderAmount(order.getAmount());
        vo.setOrderNumber(order.getNumber());
        log.info("用户下单返回的vo：{}",vo);
        return vo;
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getById(userId);

        //调用微信支付接口，生成预支付交易单
//        JSONObject jsonObject = weChatPayUtil.pay(
//                ordersPaymentDTO.getOrderNumber(), //商户订单号
//                new BigDecimal(0.01), //支付金额，单位 元
//                "苍穹外卖订单", //商品描述
//                user.getOpenid() //微信用户的openid
//        );
        JSONObject jsonObject = new JSONObject();

        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
            throw new OrderBusinessException("该订单已支付");
        }

        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));

        return vo;
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    public void paySuccess(String outTradeNo) {

        // 根据订单号查询订单
        Orders ordersDB = orderMapper.getByNumber(outTradeNo);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        orderMapper.update(orders);
    }

    public OrderDetailsVO getorderDetail(Integer id){
        //查询订单信息
        Orders order = orderMapper.getByid(id);
        //查询订单详情信息
        List<OrderDetail> orderDetails = orderDetailMapper.getDetailsBy_order_id(id);
        //封装结果
        OrderDetailsVO result = new OrderDetailsVO();
        BeanUtils.copyProperties(order,result);
        result.setOrderDetailList(orderDetails);
        return  result;
    }

    /**
     * 根据订单id取消订单
     * @param id
     */
    @Transactional
    public void cancel(Long id){
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(OrderStatusConstant.Canceled);
        orders.setCancelTime(LocalDateTime.now());
        //将订单状态设置为已取消
        orderMapper.cancel(orders);
        //删除order_detail表对应的明细
       // orderDetailMapper.deleteByorderid(id);
    }
    @Transactional
    public void repetiton(Integer id){
        //参数准备
        Orders oldorder = orderMapper.getByid(id);
        log.info("oldorder:{}",oldorder);
        Orders neworder = new Orders();
        BeanUtils.copyProperties(oldorder,neworder);
        LocalDateTime ordertime = LocalDateTime.now();
        neworder.setOrderTime(ordertime);
        neworder.setStatus(OrderStatusConstant.PendingOrders);
        neworder.setEstimatedDeliveryTime(ordertime.plusHours(INIT_HOUR));
        neworder.setNumber(String.valueOf(System.currentTimeMillis()));
        neworder.setPayStatus(OrderPayStatusConstant.UN_PAIDED);
        neworder.setCheckoutTime(null);
        log.info("neworder:{}",neworder);
        //新订单插入orders表
        orderMapper.insert(neworder);
        //订单明细插入order_detail表（批量插入)
        //1.查到该订单的所有明细
        List<OrderDetail> orderDetailList = orderDetailMapper.getByorderID(id);
        for(OrderDetail detail:orderDetailList){
            detail.setOrderId(neworder.getId());
        }
        //2.批量插入
        orderDetailMapper.insert(orderDetailList);
    }

    public PageResult gethistory(OrdersPageQueryDTO dto){
        dto.setPage((dto.getPage()-1)*dto.getPageSize());
        Long total = orderMapper.gettotals(dto);
        List<OrderPageResult> orderPageResultList = new ArrayList<>();//records数组
        List<Orders> orderslist = orderMapper.get(dto);
        for(int k=0;k<total;k++){
             Orders orders = orderslist.get(k);
             List<OrderDetail> orderDetails = orderDetailMapper.getByorderID(orders.getId().intValue());
             OrderPageResult result = new OrderPageResult();
             BeanUtils.copyProperties(orders,result);
             result.setOrderDetailList(orderDetails);
             orderPageResultList.add(result);
        }
        PageResult result = new PageResult();
        result.setTotal(total);
        result.setRecords(orderPageResultList);
        return result;
    }
}
